package server.io.code;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

public class EnDeCode_WSP extends EnDeCode_Base
{
	private static Charset charset = Charset.forName("utf-8");

	/**
	 * charset encode
	 * 
	 * @param str
	 * @return
	 */
	public static ByteBuffer encode(String a_str)
	{
		return charset.encode(a_str);
	}

	/**
	 * charset decode
	 * 
	 * @param bb
	 * @return
	 */
	public static String decode(ByteBuffer a_bb)
	{
		return charset.decode(a_bb).toString();
	}

	public static String WSP13Decode(byte[] data)
	{
		byte _firstByte = data[0];
		byte _secondByte = data[1];
		int opcode = _firstByte & 0x0F;
		// mask位
		boolean isMasked = ((_firstByte & 128) == 128);
		// 实载数据长度
		long _payloadLength = _secondByte & 0x7F;
		// 实载数据的偏移位
		int _payloadOffset = 6;
		// mask key的偏移位offset
		int _maskkeyOffset = 2;
		// mask key的长度 一般是4
		int _maskkeyLength = 4;

		if (!isMasked || opcode != 1)
		{
			try
			{
				return new String(data, "utf-8");
			}
			catch (UnsupportedEncodingException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} // not masked and opcode text

		byte[] mask = new byte[_maskkeyLength];
		if (_payloadLength == 126)
		{
			_maskkeyOffset = 4;
			_payloadOffset = 8;
			System.arraycopy(data, _maskkeyOffset, mask, 0, _maskkeyLength);
			// 后面2个bute取16位无符号整数,表示负载长度
			byte[] _uInt16Bytes = new byte[8];
			for (int i = 0; i < 2; i++)
			{
				_uInt16Bytes[i] = data[3 - i];
			}
			_payloadLength = getLong(_uInt16Bytes, true);
		}
		else if (_payloadLength == 127)
		{
			_maskkeyOffset = 10;
			_payloadOffset = 14;
			// 生成mask key
			System.arraycopy(data, _maskkeyOffset, mask, 0, _maskkeyLength);
			// 后面8个byte取64位无符号整数,是负载数据长度
			// 需要逆转字节所以是9 - i
			byte[] _uInt64Bytes = new byte[8];
			for (int i = 0; i < 8; i++)
			{
				_uInt64Bytes[i] = data[9 - i];
			}
			_payloadLength = getLong(_uInt64Bytes, true);
		}
		else
		{
			_maskkeyOffset = 2;
			_payloadOffset = 6;
			System.arraycopy(data, _maskkeyOffset, mask, 0, _maskkeyLength);
		}
		// 数据内容
		byte[] _payloadData = new byte[(int) _payloadLength];
		// 把data里实载内容分离出来
		System.arraycopy(data, _payloadOffset, _payloadData, 0,
				(int) _payloadLength);

		for (int i = 0; i < _payloadLength; i++)
		{
			_payloadData[i] = (byte) (_payloadData[i] ^ mask[i % 4]);
		}

		String _result = new String(_payloadData);
//		System.out.println("Decode length:" + " " + _payloadLength);

		return _result;

	}

	public static byte[] WSP13Encode(String data, boolean isMask)
	{
		// 临时存放需要发送的内容的字节数组
		byte[] _dataBytes = null;
		// 数据byte
		byte[] _resultBytes = null;
		try
		{
			_dataBytes = data.getBytes("UTF-8");
		}
		catch (UnsupportedEncodingException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// 是否加密数据
		// mask位置1或者不置
		byte[] _mask = null;
		byte _maskBit = 0;
		// 掩码长度
		int _maskLength = 0;
		if (isMask)
		{
			// 128 = 1000 0000 首位置1
			_maskBit = (byte) 0x80;
			// mask长度 4 byte
			_maskLength = 4;
			_mask = new byte[_maskLength];

			int _time_ms = (int) System.currentTimeMillis();
			// mask是个随机数(位),用来加密
			for (int i = 0; i < 4; i++)
			{
				_mask[i] = (byte) (_time_ms % 255);
			}
		}
		// 头长度增加了掩码
		int _headLength = _maskLength;
		// 数据长度
		int _dataLength = _dataBytes.length;

		if (_dataLength < 126)
		{
			_headLength = _headLength + 2;
			_resultBytes = new byte[_dataLength + _headLength];
			// 0x81 1000 0001 最后位1表示数据为text
			_resultBytes[0] = (byte) 0x81;
			_resultBytes[1] = (byte) (_maskBit | _dataLength);
		}
		else if (_dataLength < 0xffff)
		{
			_headLength = _headLength + 4;
			_resultBytes = new byte[_dataLength + _headLength];
			// 129
			_resultBytes[0] = (byte) 0x81;
			// 126 或者 首位掩码是1 也就是254
			_resultBytes[1] = (byte) (_maskBit | 0x7E);
			// 把数据长度转成byte
			_resultBytes[2] = (byte) (_dataLength & 0xFF);  
			_resultBytes[3] = (byte) (_dataLength >> 8 & 0xFF); 
			
			byte[] _tempBytes = getBytes((short)_dataLength, true);
			// 把数据长度转成byte
			_resultBytes[2] = _tempBytes[0];  
			_resultBytes[3] = _tempBytes[1]; 
		}
		// 如果要mask 则加密
		if (isMask)
		{
			// 把mask key放进head
			for (int i = 0, j = 2; i < _maskLength; i++, j++)
			{
				_resultBytes[j] = _mask[i];
			}
			
			for (int i = 0; i < _dataLength; i++)
			{
				_dataBytes[i] = (byte) (_dataBytes[i] ^ _mask[i % 4]);
			}
		}
		
		// 把数据打包进封装好头部的协议里
		System.arraycopy(_dataBytes, 0, _resultBytes, _headLength, _dataLength);
		
//		System.out.println("Encode length:" + " " + new String(_resultBytes));

		return _resultBytes;

	}

}
